<script lang="ts" setup>
import type { ReasonTypeNotifierRequest } from "@halo-dev/api-client";
import { ucApiClient } from "@halo-dev/api-client";
import { VLoading, VSwitch } from "@halo-dev/components";
import { stores } from "@halo-dev/ui-shared";
import { useMutation, useQuery, useQueryClient } from "@tanstack/vue-query";
import { cloneDeep } from "es-toolkit";
import { storeToRefs } from "pinia";
import { computed } from "vue";

const { currentUser } = storeToRefs(stores.currentUser());

const queryClient = useQueryClient();

const { data, isLoading } = useQuery({
  queryKey: ["notification-preferences"],
  queryFn: async () => {
    if (!currentUser.value) {
      return null;
    }

    const { data } =
      await ucApiClient.notification.notification.listUserNotificationPreferences(
        {
          username: currentUser.value?.user.metadata.name,
        }
      );

    return data;
  },
  enabled: computed(() => !!currentUser.value),
});

const {
  mutate,
  isLoading: mutating,
  variables,
} = useMutation({
  mutationKey: ["update-notification-preferences"],
  mutationFn: async ({
    state,
    reasonTypeIndex,
    notifierIndex,
  }: {
    state: boolean;
    reasonTypeIndex: number;
    notifierIndex: number;
  }) => {
    const preferences = cloneDeep(data.value);

    if (!currentUser.value || !preferences) {
      return;
    }

    if (!preferences.stateMatrix) {
      preferences.stateMatrix = [];
    }

    preferences.stateMatrix[reasonTypeIndex][notifierIndex] = state;

    const reasonTypeNotifiers = data.value?.reasonTypes
      ?.map((reasonType, currentReasonTypeIndex) => {
        return {
          reasonType: reasonType.name,
          notifiers: data.value?.notifiers
            ?.map((notifier, currentNotifierIndex) => {
              if (
                preferences.stateMatrix?.[currentReasonTypeIndex][
                  currentNotifierIndex
                ]
              ) {
                return notifier.name;
              }
            })
            .filter(Boolean),
        };
      })
      .filter(Boolean) as Array<ReasonTypeNotifierRequest>;

    return await ucApiClient.notification.notification.saveUserNotificationPreferences(
      {
        username: currentUser.value.user.metadata.name,
        reasonTypeNotifierCollectionRequest: {
          reasonTypeNotifiers,
        },
      }
    );
  },
  onSuccess() {
    queryClient.invalidateQueries({ queryKey: ["notification-preferences"] });
  },
});
</script>

<template>
  <VLoading v-if="isLoading" />

  <Transition v-else appear name="fade">
    <div class="box-border h-full w-full overflow-auto rounded-base border">
      <table class="min-w-full divide-y divide-gray-100">
        <thead class="bg-gray-50">
          <tr>
            <th
              class="px-4 py-3 text-left text-sm font-semibold text-gray-900 sm:w-96"
              scope="col"
            >
              {{ $t("core.uc_profile.notification-preferences.fields.type") }}
            </th>
            <th
              v-for="notifier in data?.notifiers"
              :key="notifier.name"
              scope="col"
              class="px-4 py-3 text-left text-sm font-semibold text-gray-900"
            >
              {{ notifier.displayName }}
            </th>
          </tr>
        </thead>
        <tbody class="divide-y divide-gray-100 bg-white">
          <template
            v-for="(reasonType, index) in data?.reasonTypes"
            :key="reasonType.name"
          >
            <HasPermission :permissions="reasonType.uiPermissions || []">
              <tr>
                <td
                  class="whitespace-nowrap px-4 py-3 text-sm font-medium text-gray-900"
                >
                  {{ reasonType.displayName }}
                </td>
                <td
                  v-for="(notifier, notifierIndex) in data?.notifiers"
                  :key="notifier.name"
                  class="whitespace-nowrap px-4 py-3 text-sm text-gray-500"
                >
                  <VSwitch
                    :model-value="data?.stateMatrix?.[index][notifierIndex]"
                    :loading="
                      mutating &&
                      variables?.reasonTypeIndex === index &&
                      variables?.notifierIndex === notifierIndex
                    "
                    @change="
                      mutate({
                        state: !data?.stateMatrix?.[index][notifierIndex],
                        reasonTypeIndex: index,
                        notifierIndex: notifierIndex,
                      })
                    "
                  />
                </td>
              </tr>
            </HasPermission>
          </template>
        </tbody>
      </table>
    </div>
  </Transition>
</template>
